package libnetdb.dm.assoc.base;

import java.util.*;

public abstract class LatticeIterator implements Iterator {
    
    private static final int NOPRUNE = 0;
    private static final int SOFTPRUNE = 1;
    private static final int HARDPRUNE = 2;
    
    private Object current, next;
    private Iterator subit;
    private LinkedHashSet toVisit = new LinkedHashSet();
    private HashSet badList = new HashSet();
    private int status = -1;     
    
    protected LatticeIterator(Object root){
        subit = nextLevel(root).iterator();
        next = getNext();
    }
    
    protected Object getNext(){
        switch(status){
            case NOPRUNE:
                Iterator it = nextLevel(current).iterator();
                while(it.hasNext()){
                    Object obj = it.next();
                    if(!badList.contains(obj)) toVisit.add(obj); 
                }
                break;
            case HARDPRUNE:
                badList.addAll(nextLevel(current));
        }
        status = NOPRUNE;        
        if(!subit.hasNext()){
            if(toVisit.size() > 0){
                subit = toVisit.iterator();
                toVisit = new LinkedHashSet();
                badList.clear();                
            }else return null;
        }
        return subit.next();
    }
    
	public Object next() {
        if(next != null){
            current = next;
            next = getNext();
            return current;
        }else return null;
	}
    
    public boolean hasNext(){
        return next != null;
    }

	public void remove(){
        throw new UnsupportedOperationException("remove");
	}
    
    public void hardPrune(){
        this.status = HARDPRUNE;
    }
    
    public void softPrune(){
        this.status = SOFTPRUNE;
    }

    abstract protected Collection nextLevel(Object object); 

}
